/*
 * File:    eg_vision.h
 * Purpose: Contains headers for Algorithm V
 */

/*
 Copyright 2009 James Youngquist, Colin Scott.

 This file is part of ElectroGladiator.  ElectroGladiator is free
 software: you can redistribute it and/or modify it under the terms
 of the GNU General Public License as published by  the Free
 Software Foundation, either version 3 of the License, or (at your
 option) any later version.

 You should have received a copy of the GNU General Public License
 along with this program.  If not, see <http://www.gnu.org/licenses/>.
*/

#ifndef _EG_VISION
#define _EG_VISION 1

#include "eg_data.h"
#include "eg_geom.h"

// for remove_pts()
#define RIGHT        &left_point  // these two are really specifying a function
#define LEFT         &right_point // for the type of point that we want to keep
#define KEEP_OTHER   1
#define IGNORE_OTHER 0

//--------------------
// FUNCTION PROTOTYPES
//--------------------

/**
 * Algorithm S finds visible line segments and trigons for p.
 * Pre: p->visible_lines contains lines to cast shadows on.  For example,
 *      cull_invisible_lines() has been called on p.
 * @param p The player
 * @param map_lines
 */
void algorithm_s (const Map *m, Player *p);


/* == Support Functions for Algorithm V == */
/**
 * Places into p->visible_players all players p can see
 * Pre: algorithm_s and cull_invisible_entities() have been run.
 * @param m Map from which to draw candidate players
 * @param p Player that wants to see
 */
void find_visible_entities(const Map *m, Player *p);

// Adds to player's visible_segments only lines from the map that are visible.
void cull_invisible_lines (const Map *m, Player *p);

/**
 * Adds to rocks and players only entities from the
 * map that are visible, i.e. in the convex hull defined by the player's FOV.
 * It also truncates lines that are intersected by the player's FOV boundaries.
 */
void cull_invisible_entities(const Map *m, Player *p, LL *players, LL *rocks);

// Removes either right or left end points from a list.  If keep_other is non
// zero, then do not remove end points of other lines that are the same as
// the opposing end point we want to remove.  For example, the middle of three
// colinear points is both a left and right end point for the two lines starting
// at the outermost points and ending in the middle.  If keep_other is
// specified, then the middle point will not be removed, assuming it is in the
// list of points.
// *keep_func is the function that will return either the left or right end
// point.  The correct function pointer is given through macros RM_RIGHT/LEFT.
void remove_pts(Point* (*keep_func)(const Player*,Line*), Map *map,
                Player *p, LL *points, int keep_other);

// Removes duplicate points from linked list of points, free memory used by
// those points.
void remove_duplicate_pts (LL *l);

/** Returns longest line needed to cover all points on a map */
double max_line_length (const Map *m);

#endif
